<template>
  <a-modal
    :mask-closable="false"
    :esc-to-close="false"
    :visible="data.show"
    :title="data.title"
    :ok-loading="data.loading"
    :modal-style="{ width: '650px' }"
    @submit="submit"
    @cancel="close"
    @finish="close"
  >
    <template #footer>
      <div class="flex-between">
        <div>
          <a-button :loading="data.loading" type="primary" @click="submit">{{ $t('components.Package.5mtcyb0rty17') }}</a-button>
          <a-button class="mr" @click="close">{{ $t('components.Package.5mtcyb0rty18') }}</a-button>
        </div>
      </div>
    </template>
    <a-form
      :model="data.formData"
      :rules="formRules"
      ref="formRef"
      auto-label-width
      labelAlign="left"
    >
      <a-form-item field="sysTem" :label="$t('components.Package.5mtcyb0rty07')" validate-trigger="blur" @change="updateOsData" name="sysTem">
        <a-radio-group v-model="tempOs.value" button-style="solid" :disabled="editDisabledFlag">
          <a-radio :value="OS.OPEN_EULER">openEuler20.03</a-radio>
          <a-radio :value="OS.CENTOS">CentOS</a-radio>
          <a-radio :value="OS.All">openEuler22.03</a-radio>
        </a-radio-group>
      </a-form-item>
      <a-form-item field="arch" :label="$t('components.Package.5mtcyb0rty32')" validate-trigger="blur" @change="updateArchData" name="arch">
        <a-radio-group v-model="tempArch.value" :disabled="editDisabledFlag">
          <a-radio :value="CpuArch.X86_64">x86_64</a-radio>
          <a-radio :disabled="OS.CENTOS === tempOs.value" :value="CpuArch.AARCH64">aarch64</a-radio>
        </a-radio-group>
      </a-form-item>
      <a-form-item field="version" :label="$t('components.Package.5mtcyb0rty33')" validate-trigger="blur" @change="updateVersionData" name="version">
        <a-radio-group v-model="tempVersion.value" :disabled="editDisabledFlag">
          <a-radio :value="OpenGaussVersionEnum.MINIMAL_LIST">{{ $t('components.Package.MINIMAL_LIST') }}</a-radio>
          <a-radio :value="OpenGaussVersionEnum.LITE">{{ $t('components.Package.LITE') }}</a-radio>
          <a-radio :value="OpenGaussVersionEnum.ENTERPRISE">{{ $t('components.Package.ENTERPRISE') }}</a-radio>
        </a-radio-group>
      </a-form-item>
      <a-form-item field="packageVersionNum" :label="$t('components.Package.5mtcyb0rty10')"  name="packageVersionNum">
        <div class="item" >
          <a-select
            v-if="!editDisabledFlag"
            v-model="tempVersionNum"
            :ref="tempVersionNum"
            :placeholder="$t('components.Package.5mtcyb0rty34')"
            :options="packageVersionNum"
            :inputmode="true"
            @search="searchVersionNum"
            @change="checkContains"
          >
          </a-select>
          <a-input v-if="editDisabledFlag" disabled :default-value="tempVersionNum"></a-input>
          <br><p class="ant-upload-hint" v-if="!contains">
          {{ $t('components.Package.5mtcyb0rty35') }}
          <a-button type="text" href="https://opengauss.org/zh/download/archive/">{{ $t('components.Package.5mtcyb0rty36') }}</a-button>
          {{ $t('components.Package.5mtcyb0rty37') }} </p>
        </div>
      </a-form-item>
      <a-form-item field="name" :label="$t('components.Package.5mtcyb0rty06')" name="name">
        <a-input
          v-model="data.formData.name"
          :placeholder="$t('components.Package.5mtcyb0rty06')"
          @input="data.isNameDirty = true"
          :disabled="editDisabledFlag"
        />
      </a-form-item>
      <a-form-item field="path" :label="$t('components.Package.5mtcyb0rty38')" name="path">
        <div class="item" style="width:100%" >
          <a-textarea v-model="tempPackageUrl" show-count :maxlength="1000" :default-value="data.formData.packageUrl"  readonly></a-textarea>
          <p class="ant-upload-hint" v-if="data.formData.packageUrl && netStatus">
            {{ $t('components.Package.5mtcyb0rty39') }}
            <a-button type="text" @click="uploadStatusChange">{{ $t('components.Package.5mtcyb0rty22') }}</a-button>
          </p>
          <p v-if="!netStatus" class="ant-upload-hint">{{ $t('components.Package.5mtcyb0rty40') }}</p>
        </div>
      </a-form-item>
      <a-form-item
        v-if="uploadStatusTag.value === true || !netStatus"
        field="packagePath"
        :label="$t('components.Package.5mtcyb0rty41')"
        name="packagePath"
      >
        <a-upload
          v-model:file-list="fileListPPPP"
          :limit="1"
          :auto-upload="false"
          draggable
          @before-remove="handleBeforeRemove"
          @change="handleFileUpload"
        >
          <template>
            <div class="upload-info flex-col">
              <div class="flex-col">
                <div >
                  <svg-icon icon-class="clouduploadsharp" class="icon-size image mb"></svg-icon>
                </div>
                <div class="tips-1">
                  <span>{{
                      $t('components.Package.5mtcyb0rty42')
                    }}
                    <a-button  #upload-button >{{ $t('components.Package.5mtcyb0rty43') }}</a-button>
                  </span>
                </div>
              </div>
            </div>
          </template>
        </a-upload>
      </a-form-item>
      <a-form-item
        v-if="(uploadStatusTag || !netStatus) && progressPercent.valueOf() > 0"
      >
        <a-progress :percent="progressPercent">{{progressPercent.valueOf()}}</a-progress>
      </a-form-item>
    </a-form>
  </a-modal>

</template>

<script setup lang="ts">
import { KeyValue } from '@/types/global'
import { FormInstance } from '@arco-design/web-vue/es/form'
import { nextTick, reactive, ref, toRaw, computed, isReadonly, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { CpuArch, OS } from '../../../../../../plugins/base-ops/web-ui/src/types/os'
import { OpenGaussVersionEnum } from '@/types/ops/install'
import {
  batchPackageOnline,
  batchPackageUpload,
  getVersionNum,
  checkNetStatus,
  checkVersionNumber,
  packageUploadUpdate,
  delPkgTar, getSysUploadPath, hasPkgName, download, packageOnlineUpdate
} from '@/api/ops'
import dayjs from 'dayjs'
import { FileItem, Message, Modal } from '@arco-design/web-vue'
import message from '@arco-design/web-vue/es/message'
import Socket from '@/utils/websocket'
import axios from 'axios'
import { Path } from '@antv/x6'
import isValid = Path.isValid;
const { t } = useI18n()

const data = reactive<KeyValue>({
  show: false,
  title: '',
  isViewVersion: false,
  formData: {
    name: '',
    type: 'openGauss',
    packageId: '',
    os: OS.CENTOS,
    osVersion: 7,
    cpuArch: CpuArch.AARCH64,
    packageVersion: OpenGaussVersionEnum.MINIMAL_LIST,
    packageVersionNum: '',
    packageUrl: '',
    packagePath: {},
    remark: ''
  },
  cpuArchList: [],
  packageVersionList: [],
  typeList: [],
  fileList: [],
  type: '',
  systemUploadPath: '',
  isNameDirty: false
})

interface UploadInfo {
  realPath: string,
  realName: string,
  name: string,
  file: File
}

const tempVersionNum = ref('5.0.2')

const contains = ref(true)
const checkContains = (inputValue:any) => {
  tempVersionNum.value = inputValue
  if (inputValue && inputValue !== '') {
    data.formData.packageVersionNum = inputValue
    contains.value = packageVersionNum.value.some(item => item === data.formData.packageVersionNum)
    if (contains.value === false) {
      const params = {
        os: data.formData.os,
        cpuArch: data.formData.cpuArch,
        packageVersion: data.formData.packageVersion,
        packageVersionNum: data.formData.packageVersionNum
      }
      checkVersionNumber(params).then((res) => {
        if (res.code !== 200) {
          Message.error({
            content: t('components.Package.5mtcyb0rty44', { versionNum: data.formData.packageVersionNum })
          })
          data.formData.packageVersionNum = ''
          tempVersionNum.value = null
        } else {
          getPackageUrl()
        }
      }) .catch(error => {
        message.error({
          content: t('components.Package.5mtcyb0rty44', { versionNum: data.formData.packageVersionNum })
        })
        data.formData.packageVersionNum = '5.0.0'
        tempVersionNum.value = '5.0.0'
      })
    } else {
      getPackageUrl()
    }
  }
}

const searchVersionNum = (value:any) => {
  data.formData.packageVersionNum = (value != null && value !== '') ? value : undefined
}

const formRules = computed(() => {
  return {
    packageVersionNum: [
      { required: true, message: t('components.Package.5mtcyb0rty45') }
    ],
    name: [
      { required: true, message: t('components.Package.5mtcyb0rty46') },
      {
        validator: (value: any, cb: any) => {
          return new Promise((resolve) => {
            hasPkgName(value).then((res: KeyValue) => {
              if (res.data && !editDisabledFlag.value) {
                cb(t('components.Package.5mtcyb0rty47'))
                isValid.value = false
                resolve(false)
              } else {
                resolve(true)
              }
            })
          })
        }
      }
    ],
    packagePath: [{
      validator: (value: any, cb: any) => {
        return new Promise((resolve, reject) => {
          if (data.fileList.length <= 0 && uploadStatusTag.value === true) {
            cb(t('components.Package.5mtcyb0rty48'))
            isValid.value = false
            resolve(false)
            return
          } else {
            resolve(true)
          }
        })
      }
    }]
  }
})

const fileListPPPP = ref([])
const uploadStatusTag = reactive({ value: false })
const uploadStatusChange = () => {
  uploadStatusTag.value = true
}
const uploadFileTag = reactive({ value: true })
const handleFileUpload = (file:any) => {
  data.fileList = file[0]
}

const handleBeforeRemove = (file: FileItem) => {
  return new Promise((resolve, reject) => {
    if (file.status === 'done') {
      Modal.confirm({
        title: t('packageManage.AddPackageDlg.5myq6nnecc45'),
        content: `${t('packageManage.AddPackageDlg.5myq6nnecc45')}${
          file.name
        }${t('packageManage.AddPackageDlg.5myq6nnecc46')}`,
        onOk: () => {
          delPkgTar(
            data.formData.packagePath?.realPath,
            data.formData.packageId
          ).then((res) => {
            data.formData.packagePath = {}
            emits(`finish`)
            resolve(true)
          })
        },
        onCancel: () => reject('cancel')
      })
    } else {
      resolve(true)
    }
  })
}

// web socket
const downloadWs = ref<Socket<any, any> | undefined>()
const processVisible = ref(false)
const percentLoading = ref(false)
const currPercent = ref<number>(0)

watch(currPercent, (newValue) => {
  if (newValue === 100) {
    processVisible.value = false
  }
})

const getUploadPath = () => {
  data.uploadPathLoading = true
  getSysUploadPath()
    .then((res: KeyValue) => {
      if (Number(res.code) === 200) {
        data.systemUploadPath = res.data
      }
    })
}

// init
const getSystemSetting = () => {
  getSysUploadPath().then((res) => {
    data.systemUploadPath = res.data
  }) .catch(error => {
    console.error('Error fetching 285:', error)
  })
}

const packageVersionNum = ref([])
const fetchVersionNum = () => {
  getVersionNum().then((res: KeyValue) => {
    packageVersionNum.value = []
    if (Number(res.code) === 200) {
      res.data.forEach(item => { packageVersionNum.value.push(item) })
    } else {
      Message.error({
        content: t('components.Package.5mtcyb0rty49')
      })
    }
  }) .catch(error => {
    console.error(error)
  })
}

const tempPackageUrl = ref('')
const getPackageUrl = () => {
  const params = {
    os: data.formData.os,
    osVersion: data.formData.osVersion,
    cpuArch: data.formData.cpuArch,
    openGaussVersion: data.formData.packageVersion,
    openGaussVersionNum: data.formData.packageVersionNum
  }
  checkVersionNumber(params).then((res) => {
    if (res.code === 200) {
      if (res.data.length) {
        data.formData.packageUrl = res.data[0].packageUrl
      } else {
        data.formData.packageUrl = res.data.packageUrl
      }
      tempPackageUrl.value = data.formData.packageUrl
    } else {
      console.log('error')
    }
    let noExtensionName = ''
    let packageNameList = data.formData.packageUrl.split('/').pop()
    let namelist = packageNameList?.split('.') || []
    namelist.length && namelist.pop()
    namelist.length && namelist.pop()
    const now = dayjs();
    const curTime = now.format('YYMMDD')
    noExtensionName = namelist.join('.') + curTime
    data.formData.name = noExtensionName
  }) .catch(error => {
    console.error({
      content: error + data.formData.packageVersionNum
    })
  })
}

const netStatus = ref(false)
const getConnectStatus = () => {
  checkNetStatus().then((res) => {
    netStatus.value = res.code === 200
  }) .catch(error => {
    console.error('net connect error:', error)
  })
}

const wsBusinessId = ref('')
const editDisabledFlag = ref(false)
const open = (
  type: string,
  packageData?: KeyValue,
  addOptionFlag?: number,
  wsBusiness?: string
) => {
  getUploadPath()
  fetchVersionNum()
  data.type = type
  if (type === 'create') {
    data.title = t('components.Package.5mtcyb0rty50')
    uploadStatusTag.value = false
    editDisabledFlag.value = false
  } else {
    data.title = t('components.Package.5mtcyb0rty51')
    editDisabledFlag.value = true
  }
  wsBusinessId.value = wsBusiness
  let versionnum = '5.0.2'
  getConnectStatus()
  if (!packageData) {
    Object.assign(data.formData, {
      packageId: '',
      os: OS.CENTOS,
      osVersion: '7',
      cpuArch: CpuArch.X86_64,
      packageVersion: OpenGaussVersionEnum.MINIMAL_LIST,
      packageVersionNum: versionnum,
      packageUrl: '',
      type: 'openGauss'
    })
    data.fileList = []
    data.formData.packagePath = {}
    fileListPPPP.value = []
    tempVersionNum.value = data.formData.packageVersionNum
    getPackageUrl()
  } else {
    Object.assign(data.formData, {
      packageId: packageData.packageId || '',
      name: packageData.name || '',
      os: packageData.os || OS.CENTOS,
      osVersion: packageData.osVersion || '7',
      cpuArch: packageData.cpuArch || CpuArch.X86_64,
      packageVersion: packageData.packageVersion || OpenGaussVersionEnum.MINIMAL_LIST,
      packageVersionNum: packageData.packageVersionNum || versionnum,
      packageUrl: packageData.packageUrl || '',
      packagePath: packageData.packagePath as UploadInfo,
      type: packageData.type || 'openGauss',
      remark: packageData.remark
    })
    if (packageData.cpuArch == CpuArch.AARCH64 && packageData.os == '') {
      data.formData.os = OS.OPEN_EULER
      data.formData.osVersion = '20.03'
    }
    if (packageData.cpuArch == CpuArch.AARCH64 && packageData.os == OS.CENTOS) {
      data.formData.cpuArch = CpuArch.X86_64
    }
    if (data.formData.packagePath?.realPath) {
      data.fileList = [{
        uid: '-1',
        name: data.formData.packagePath.name,
        url: data.formData.packagePath.realPath
      }]
      uploadStatusTag.value = false
    }
    if (data.formData.name == '') {
      getPackageUrl()
    }
  }
  if (addOptionFlag === 0) {
    getPackageUrl()
    uploadStatusTag.value = false
  } else if (addOptionFlag === 1) {
    data.formData.name = packageData.name ? packageData.name : ''
    uploadStatusTag.value = true
  }
  tempOs.value = data.formData.os
  if (data.formData.osVersion == '22.03' && data.formData.os == OS.OPEN_EULER) {
    tempOs.value = OS.All
  }
  tempArch.value = data.formData.cpuArch
  tempVersion.value = data.formData.packageVersion
  tempVersionNum.value = data.formData.packageVersionNum
  tempPackageUrl.value = data.formData.packageUrl
  data.show = true
  progressPercent.value = 0
}

defineExpose({
  open
})
const tempOs = reactive({ value: OS.CENTOS })
const updateOsData = (value:string) => {
  tempOs.value = value.target.value
  if (tempOs.value === OS.CENTOS) {
    if (data.formData.cpuArch === CpuArch.AARCH64) {
      tempArch.value = CpuArch.X86_64
      data.formData.cpuArch = CpuArch.X86_64
    }
    data.formData.os = OS.CENTOS
    data.formData.osVersion = '7'
  } else if (tempOs.value === OS.All) {
    data.formData.os = OS.OPEN_EULER
    data.formData.osVersion = '22.03'
  } else if (tempOs.value === OS.OPEN_EULER) {
    data.formData.os = OS.OPEN_EULER
    data.formData.osVersion = '20.03'
  }
  getPackageUrl()
}
const tempArch = reactive({ value: CpuArch.X86_64 })
const updateArchData = (value:string) => {
  if (data.formData.os === OS.CENTOS && value.target.value === CpuArch.AARCH64) {
    tempArch.value = CpuArch.X86_64
    data.formData.cpuArch = CpuArch.X86_64
  } else {
    tempArch.value = value.target.value
    data.formData.cpuArch = tempArch.value
  }
  getPackageUrl()
}
const tempVersion = reactive({ 'value': OpenGaussVersionEnum.MINIMAL_LIST })
const updateVersionData = (value:string) => {
  tempVersion.value = value.target.value
  data.formData.packageVersion = tempVersion.value
  getPackageUrl()
}

const formRef = ref<null | FormInstance>(null)
const emits = defineEmits([`finish`, `downloadStart`])
const submitLoading = ref(false)
const progressPercent = ref(0)
const submit = async () => {
  let isisvalid = await formRef.value?.validate()
  if (isisvalid && editDisabledFlag.value !== true) {
    console.log('isValild false')
  } else {
    if (uploadStatusTag.value) {
      if (data.formData.packageId && data.formData.packageId != '') {
        if (progressPercent.value === 0) {
          const formData = new FormData
          formData.append('packageId', data.formData.packageId)
          formData.append('uploadFile', data.fileList.file)
          axios({
            url: `/plugins/base-ops/installPackageManager/v2/update/upload/`,
            method: 'POST',
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            onUploadProgress: (event) => {
              let percent
              if (event.lengthComputable) {
                percent = Math.round((event.loaded * 100) / event.total)
              }
              progressPercent.value = percent ? Number((percent * 0.01).toFixed(2)) : 0
            },
            data: formData
          }).then((res) => {
            if (res.code === 200) {
              close()
            }
          }).catch((error) => {
            console.log(error)
          })
        }
      } else {
        const formData = new FormData
        formData.append('name', data.formData.name)
        formData.append('os', data.formData.os)
        formData.append('cpuArch', data.formData.cpuArch)
        formData.append('packageVersionNum', data.formData.packageVersionNum)
        formData.append('packageUrl', data.formData.packageUrl)
        formData.append('packageVersion', data.formData.packageVersion)
        formData.append('uploadFile', data.fileList.file)
        formData.append('osVersion', data.formData.osVersion)
        if (progressPercent.value === 0) {
          axios({
            url: `/plugins/base-ops/installPackageManager/v2/save/upload/`,
            method: 'POST',
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            onUploadProgress: (event) => {
              let percent
              if (event.lengthComputable) {
                percent = Math.round((event.loaded * 100) / event.total)
              }
              progressPercent.value = percent ? Number((percent * 0.01).toFixed(2)) : 0
            },
            data: formData
          }).then((res) => {
            if (res.code === 200) {
              close()
            }
          }).catch((error) => {
            console.log(error)
          })
        }
      }
    } else {
      if (!editDisabledFlag.value) {
        const params = {
          name: data.formData.name,
          os: data.formData.os,
          osVersion: data.formData.osVersion,
          cpuArch: data.formData.cpuArch,
          openGaussVersion: data.formData.packageVersion,
          openGaussVersionNum: data.formData.packageVersionNum,
          downloadUrl: data.formData.packageUrl,
          wsBusinessId: wsBusinessId.value
        }
        emits('downloadStart', data.formData.name)
        batchPackageOnline(params).then((res) => {
          if (res.code === 200) {
            data.show = false
          }
        }).catch((error) => {
          console.log(error)
        })
      } else if (data.formData.packageId) {
        const params = new URLSearchParams()
        params.append('packageId', data.formData.packageId)
        params.append('wsBusinessId', wsBusinessId.value)
        const config = {
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          }
        }
        emits('downloadStart', data.formData.name)
        packageOnlineUpdate(params, config)
          .then(res => {
            if (res.code === 200) {
              data.show = false
            }
          })
          .catch(error => {
            console.error('online update error:', error)
          })
      } else {
        console.log('download error')
      }
    }
  }
}
const close = () => {
  try {
    if (downloadWs.value && downloadWs.value instanceof WebSocket && typeof downloadWs.value.close === 'function') {
      downloadWs.value.close(1000, 'Normal closure')
    }
  } catch (error) {
    console.error('Error closing WebSocket:', error)
  } finally {
    data.show = false
    data.oldPwd = ''
    Object.assign(data.formData, {
      name: '',
      type: 'openGauss',
      packageId: '',
      os: '',
      cpuArch: '',
      packageVersion: '',
      packageVersionNum: '',
      packageUrl: '',
      packagePath: {},
      remark: ''
    })
    tempOs.value = OS.CENTOS
    tempArch.value = CpuArch.X86_64
    tempVersion.value = OpenGaussVersionEnum.MINIMAL_LIST
    tempVersionNum.value = ''
    uploadStatusTag.value = false
    nextTick(() => {
      formRef.value?.clearValidate()
      formRef.value?.resetFields()
      data.fileList = []
      data.formData.packagePath = {}
      fileListPPPP.value = []
    })
  }

}
</script>

<style scoped>
:deep(.ant-upload-hint) {
  color:lightgrey;
}

:deep(.arco-radio-checked.arco-radio-disabled .arco-radio-label) {
  color: var(--color-hw-text-2);
}

:deep(.arco-radio-disabled .arco-radio-label) {
  color: var(--color-text-3);
}

:deep(.arco-input-wrapper .arco-input[disabled]){
  -webkit-text-fill-color: var(--color-text-3);
}
:deep(.arco-progress-type-circle) {
  display: table-column;
}

:deep(.arco-upload-list-item-name-link .arco-upload-list-item-file-icon .arco-upload-list-item-file-icon) {
  color: black;
}
</style>
